#include "qfaceobject.h"
#include <QDebug>
#include <iostream>
#include <exception>
#include <fstream>

QFaceObject::QFaceObject(QObject *parent)
    : QObject{parent}, fengineptr(nullptr)
{
    // 初始化人脸识别引擎
    seeta::ModelSetting FDmode("E:/code/Qtproject/package/SeetaFace/bin/model/fd_2_00.dat", seeta::ModelSetting::GPU, 0);
    seeta::ModelSetting PDmode("E:/code/Qtproject/package/SeetaFace/bin/model/pd_2_00_pts5.dat", seeta::ModelSetting::GPU, 0);
    seeta::ModelSetting FRmode("E:/code/Qtproject/package/SeetaFace/bin/model/fr_2_10.dat", seeta::ModelSetting::GPU, 0);
    this->fengineptr = new seeta::FaceEngine(FDmode, PDmode, FRmode);

    // 加载人脸数据库并添加调试信息
    QString faceDbPath = "./face.db";
    qDebug() << "正在加载人脸数据库:" << faceDbPath;
    
    bool loadResult = this->fengineptr->Load("./face.db");
    if (loadResult) {
        qDebug() << "人脸数据库加载成功";
    } else {
        qDebug() << "人脸数据库加载失败";
    }

    // 使用默认数据库连接
    database = QSqlDatabase::database();
    if (!database.isOpen())
    {
        qDebug() << "QFaceObject无法访问默认数据库连接";
    }
    else
    {
        qDebug() << "QFaceObject使用默认数据库连接成功";
    }
}

QFaceObject::~QFaceObject()
{
    delete this->fengineptr;
}

// 辅助函数：将cv::Mat转换为SeetaImageData格式
SeetaImageData QFaceObject::convertMatToSeetaImage(cv::Mat &faceImage)
{
    SeetaImageData seetaImage;
    seetaImage.data = faceImage.data;
    seetaImage.width = faceImage.cols;
    seetaImage.height = faceImage.rows;
    seetaImage.channels = faceImage.channels();
    return seetaImage;
}

// 人脸注册函数
int64_t QFaceObject::face_register(cv::Mat &faceImage)
{
    // 先查询是否已存在相似人脸，使用默认阈值0.65
    int64_t existingFaceId = face_query_for_duplicate_check(faceImage, 0.65f);

    if (existingFaceId >= 0)
    {
        // 人脸已存在，返回负值表示注册失败
        qDebug() << "人脸已存在，已有ID:" << existingFaceId;
        return -1;
    }

    SeetaImageData seetaImage = convertMatToSeetaImage(faceImage);
    int64_t newFaceId = this->fengineptr->Register(seetaImage);
    if (newFaceId >= 0)
    {
        fengineptr->Save("./face.db");
        qDebug() << "新人脸注册成功，ID:" << newFaceId;
    }
    return newFaceId;
}

// 人脸查询函数，支持自定义相似度阈值
void QFaceObject::face_query(cv::Mat &faceImage, float similarityThreshold)
{
    SeetaImageData seetaImage = convertMatToSeetaImage(faceImage);
    float similarity = 0;
    int64_t faceId = fengineptr->Query(seetaImage, &similarity);

    qDebug() << "人脸查询结果 - faceId:" << faceId << "，相似度:" << similarity << "，阈值:" << similarityThreshold;
    
    // 如果查询到的相似度小于阈值，返回-1表示未找到匹配
    if (faceId >= 0 && similarity >= similarityThreshold)
    {
        emit sendEmployeeDataToClient(faceId);
        qDebug() << "找到匹配人脸，ID:" << faceId << "，相似度:" << similarity;
    }
    else
    {
        emit sendEmployeeDataToClient(-1);
        qDebug() << "未找到匹配人脸，最高相似度:" << similarity << "，阈值:" << similarityThreshold;
        
        // 如果相似度为0，可能是人脸数据库问题
        if (similarity == 0) {
            qDebug() << "警告：相似度为0，可能是人脸数据库未正确加载或图像质量问题";
        }
    }
}

// 用于重复检测的人脸查询函数，返回匹配的人脸ID或-1
int64_t QFaceObject::face_query_for_duplicate_check(cv::Mat &faceImage, float similarityThreshold)
{
    SeetaImageData seetaImage = convertMatToSeetaImage(faceImage);
    float similarity = 0;
    int64_t faceId = fengineptr->Query(seetaImage, &similarity);

    // 如果查询到的相似度大于等于阈值，返回匹配的人脸ID
    if (faceId >= 0 && similarity >= similarityThreshold)
    {
        qDebug() << "检测到重复人脸，ID:" << faceId << "，相似度:" << similarity;
        return faceId;
    }
    else
    {
        qDebug() << "未检测到重复人脸，最高相似度:" << similarity << "，阈值:" << similarityThreshold;
        return -1;
    }
}
